
open Seppo_lib

type t_f = Csexp.t -> (unit, string) result Lwt.t option

let test_do_wait () = 
  let now = Ptime.epoch
  and jitter = 0.0 in
  Job.do_wait ~now ~jitter 1
  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-01T000100Z";
  Job.do_wait ~now ~jitter 10
  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-01T170300Z";
  Job.do_wait ~now ~jitter 13 (* maximum wait interval *)
  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-06T163100Z";
  Job.do_wait ~now ~jitter 14 (* maximum wait all interval summed up *)
  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-12T090300Z"

let test_compute_fn () = 
  let now = Ptime.epoch
  and jitter = 0. in
  let now = Job.do_wait ~now ~jitter 10
  and nonce = "foo bar baz" |> Bytes.of_string |> Job.compute_nonce in
  let Task j = Job.compute_fn now 10 nonce in
  j |> Assrt.equals_string __LOC__ "1970-01-01T170300Z.10.776976811.s"

let test_job () =
  Logr.debug (fun m -> m "%s" "job_test.job");
  let run_job_yes : t_f = function
    | Csexp.Atom s ->
      Logr.debug (fun m -> m "%s run_job_yes: %s" "job_test.job" s);
      Some (Lwt.return (Ok ()))
    | _ -> None in
  let run_job_no _ =
    Logr.debug (fun m -> m "%s run_job_no" "job_test.job");
    None in
  (* call functions from fkts with argument v until first return Some _ *)
  let run_until_some (fkts : t_f list) (v : Csexp.t) =
    fkts |> List.fold_left
      (fun r fkt ->
         match r with
         | Some _ as r -> r (* we have a result, don't call more workers *)
         | None        -> fkt v
      )
      None
  in
  match "fil" ,
        (Csexp.Atom "xyz")
        |> run_until_some [run_job_no; run_job_no; run_job_yes; run_job_yes; run_job_no]
  with
  | _,None -> Lwt.return ()
  | fn,Some x ->
    let%lwt x = x in
    (match x with
     | Ok ()   ->
       fn |> Assrt.equals_string __LOC__ "fil" |> Lwt.return
     | Error x ->
       x  |> Assrt.equals_string __LOC__ "" |> Lwt.return
    )

let test_jitter () =
  let now = Ptime.epoch in
  let jitter = 0.0 in
  Job.do_wait ~now ~jitter 3  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-01T000700Z";
  Job.do_wait ~now ~jitter 13  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-06T163100Z";
  let jitter = -0.05 in
  Job.do_wait ~now ~jitter 3  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-01T000639Z";
  Job.do_wait ~now ~jitter 13  |> Job.rfc3339
  |> Assrt.equals_string __LOC__ "1970-01-06T094127Z";
  ()

let () =
  test_do_wait ();
  test_compute_fn ();
  test_jitter ();
  Lwt_main.run (test_job ())
